Add JA4/TLS fingerprint debug endpoint at /_ts/debug/ja4#646
Conversation
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Summary
Thanks for adding the temporary JA4/TLS debug endpoint and route coverage. The implementation is straightforward and CI is green, but before this ships I think the endpoint should be explicitly gated so it cannot become a public same-origin fingerprint reflection API by default.
Additional finding folded into body
Document the debug endpoint and config gate
If this endpoint is retained behind a new trusted-server.toml debug flag, please also document the flag and endpoint behavior in the API/config docs. The docs should make clear that this is temporary/debug-only, disabled by default, what fields are returned (ja4, h2_fp, cipher, tls_version, user-agent, ch-mobile, ch-platform), the fallback values, and that the response uses Cache-Control: no-store, private.
aram356
left a comment
There was a problem hiding this comment.
Summary
Adds a GET /_ts/debug/ja4 endpoint to the Fastly adapter for inspecting JA4/H2/TLS fingerprint metadata and Client Hints. CI is green and the route-level test correctly exercises dispatch. Two blocking concerns remain before this can ship: the endpoint is reachable unauthenticated by default (carried over from the prior review round), and its Cache-Control: no-store, private header is silently overridable by operator [response_headers] because the response flows through finalize_response.
Blocking
🔧 wrench
- Public-by-default fingerprint reflection oracle:
/_ts/debug/ja4is not protected by basic-auth in the default config and reflects values JS cannot otherwise read directly (main.rs:217). Gate behind a debug flag, restrict to staging, or move under an admin path. Cache-Controloverridable by operator[response_headers]: handler-setno-store, privateis replaced byfinalize_responseif operators setCache-Controlin[response_headers](main.rs:134 → main.rs:349-351). Handle the route alongside/healthbeforeroute_requestruns.
Non-blocking
♻️ refactor
- Unit test duplicates the route-level test: identical assertions; route-level test is strictly stronger (main.rs:359-411 vs route_tests.rs:253-317).
🤔 thinking
- Defensive
Varyheader:User-Agent, Client-Hints, and TLS metadata vary the response — useful backstop if the override onCache-Controlis fixed (main.rs:133-136).
🌱 seedling
- Track removal: PR description and code call this "temporary" but neither has a removal trigger or follow-up issue. Add a
// TODO: remove after JA4 evaluation completes — see #645and consider a scheduled cleanup PR.
📝 note
- Bypasses platform abstraction for fields that have one:
tls_protocolandtls_cipherare available viaruntime_services.client_info()(main.rs:115-116). JA4/H2 are Fastly-specific so direct calls are unavoidable for those; mixing in the abstraction for fields that have one would be more consistent.
⛏ nitpick
- Use
header::CACHE_CONTROLin test assertions instead of"cache-control"(main.rs:376, route_tests.rs:282). - Extract magic strings to
consts:"unavailable","not sent","none"and label strings are duplicated across production and both tests (main.rs:113-130).
CI Status
- fmt: PASS
- clippy: PASS
- rust tests: PASS
- js tests: PASS
- wasm32-wasip1 release build: PASS
ChristianPavilonis
left a comment
There was a problem hiding this comment.
Summary
I reviewed the current branch again and am only leaving findings that do not appear to duplicate the existing pending review comments. These are non-blocking cleanup/documentation accuracy items.
Summary
GET /_ts/debug/ja4endpoint to the Fastly adapter to surface JA4 TLS fingerprint, H2 fingerprint, cipher suite, TLS version, user-agent, and selected Client Hints for browser fingerprint evaluation/_ts/debug/ja4router pathChanges
crates/trusted-server-adapter-fastly/src/main.rsbuild_ja4_debug_response, registeredGET /_ts/debug/ja4, and added unit coverage for fallback response fieldscrates/trusted-server-adapter-fastly/src/route_tests.rs/_ts/debug/ja4dispatch, content type, and fallback body valuesCloses
Closes #645
Test plan
cargo fmt --all -- --checkcargo test --workspacecargo clippy --workspace --all-targets --all-features -- -D warningscargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1cargo test,vitest,integration tests,browser integration tests,format-docs,format-typescript,cargo fmt, and CodeQLfastly compute serveChecklist
unwrap()in production code - useexpect("should ...")logmacros (notprintln!)